#include "asr_stream.h"
#include "asr_punctuation.h"
#include "llm_server.h"
#include "port_audio.h"
#include "tts_thread.h"

#include <memory>
#include <signal.h>
#include <unistd.h>

#include "conf.h"

namespace {
    std::unique_ptr<AsrStream> asr;
    std::unique_ptr<LlmServer> lserver;
    std::unique_ptr<TtsThread> tts;

    void llm_server_callback(const std::string & content) {
        sys_log("set dataset input finished : true");
        tts->notifyInputFinished();
    }

    void llm_server_stream_callback(const std::string & content) {
        sys_log("send llm server str(%s) to tts.", content.c_str());
        tts->appendText(content);
    }

    void waitForTtsAudioEmpty(void) {
        // 等待 tts 文本缓冲区空，也就是语音合成只剩下最后一句了
        while (!tts->bufferEmpty()) {
            sys_log("waiting for tts buffer empty......");
            sleep(1);
        }
        sys_log("tts buffer empty!");
    
        // 设置 tts 回调函数
        bool audio_buffer_empty = false;
        tts->setBufferTransitionToEmptyCallback([&audio_buffer_empty]() {
            audio_buffer_empty = true;
        });
    
        // 等待语音播放完成
        while (!audio_buffer_empty) {
            sys_log("waiting for audio buffer empty......");
            sleep(1);
        }
    
        tts->setBufferTransitionToEmptyCallback(nullptr);
        sys_log("audio buffer empty!");
    }

    AsrStream::asrContinueEnum asr_callback(const std::string & asr_res) {
        sys_log("%s", asr_res.c_str());

        if (tts->bufferEmpty() && tts->audioBufferEmpty()) {
            
            asr->pause();

            sys_log("send question:'%s' to gpt server.", asr_res.c_str());
            lserver->post_request(asr_res + "，回答不要出现英文字符和特殊符号。");  // 会阻塞进程

            // 等待语音播放完成
            waitForTtsAudioEmpty();
            
            asr->resume();

            return AsrStream::asrContinue;  // 停止 asr 识别
        }

        sys_log("return asrContinue......");
        return AsrStream::asrContinue; // 继续 asr 识别
    }

    void signalHandler(int signum) {
        sys_log("signal handler .... exit ......");

        if (asr) {
            sys_log("asr pause.");
            asr->pause();
        }

        if (tts) {
            sys_log("audio stop.");
            tts->audioStop();
        }


        if (tts)    tts.reset();
        if (asr)    asr.reset();
        if (lserver)    lserver.reset();
        exit(signum);  // 释放资源
    }
}

int main(void) {
    signal(SIGINT, signalHandler);

    // 初始化全局的 portAudio 库
    std::unique_ptr<PortAudioManager> pam = std::make_unique<PortAudioManager>();

    // 初始化语音合成类
    tts = std::make_unique<TtsThread>();
    tts->notifyInputFinished();
    tts->audioStart();

    // 初始化访问网络大模型
    lserver = std::make_unique<LlmServer>();
    lserver->setUserCallback(llm_server_callback);
    lserver->setUserStreamCallback(llm_server_stream_callback);

    // 初始化语音识别类
    AsrPunctuation punc("/opt/sherpa-onnx/sherpa-onnx-punct-model/model.onnx");
    asr = std::make_unique<AsrStream>(
        "/opt/sherpa-onnx/sherpa-onnx-streaming-zipformer-zh/encoder-epoch-99-avg-1.onnx",
        "/opt/sherpa-onnx/sherpa-onnx-streaming-zipformer-zh/decoder-epoch-99-avg-1.onnx",
        "/opt/sherpa-onnx/sherpa-onnx-streaming-zipformer-zh/joiner-epoch-99-avg-1.onnx",
        "/opt/sherpa-onnx/sherpa-onnx-streaming-zipformer-zh/tokens.txt",
        "",
        &punc
    );
    asr->setAsrCallback(asr_callback);



    lserver->post_request("你是一个医院中的机器人，现在打招呼并且询问病人有什么需要询问的事情。");

    waitForTtsAudioEmpty();

    // 启动语音识别
    sys_log("asr resume ->");
    asr->resume();
    
    for(;;);

    exit(0);
}
